<template>
  <div class='app-container'>
    <!-- 主容器 -->
    <div ref="graphContainer" class="parent-wrapper"></div>
    <!-- 顶部功能按钮 -->
    <a-button type="primary" style="position: fixed; top: 15px; left: 240px; z-index: 10;" @click="createGraph">创建组</a-button>
    <a-button type="primary" style="position: fixed; top: 15px; left: 325px; z-index: 10;" @click="zoomIn">放大</a-button>
    <a-button type="primary" style="position: fixed; top: 15px; left: 405px; z-index: 10;" @click="zoomOut">缩小</a-button>
    <a-button type="primary" style="position: fixed; top: 15px; left: 485px; z-index: 10;" @click="actualSize">恢复</a-button>
    <a-button type="primary" style="position: fixed; top: 15px; left: 565px; z-index: 10;" @click="show">展示</a-button>
    <!-- 属性的信息面板 -->
    <div class="status-info-panel" v-show="graph && graph.getSelectionCells().length === 1">
      <a-form-model :model="stateForm" :label-col="{ span: 8 }" :wrapper-col="{ span: 16}">
        <a-collapse accordion>
          <a-collapse-panel key="1" header="宽高位置">
            <a-form-model-item label="宽度">
              <a-input class="num-input" v-model="stateForm.width" @blur="ChangeData('width')" @pressEnter="ChangeData('width')" placeholder="未选中" style="width: 100%;">
              </a-input>
            </a-form-model-item>
            <a-form-model-item label="高度">
              <a-input class="num-input" v-model="stateForm.height" @blur="ChangeData('height')" @pressEnter="ChangeData('height')" placeholder="未选中" style="width: 100%;">
              </a-input>
            </a-form-model-item>
            <a-form-model-item label="X">
              <a-input v-model="stateForm.x" @blur="ChangeData('x', 'x')" @pressEnter="ChangeData('x', 'x')" placeholder="未选中" style="width: 100%" />
            </a-form-model-item>
            <a-form-model-item label="Y">
              <a-input v-model="stateForm.y" @blur="ChangeData('y', 'y')" @pressEnter="ChangeData('y', 'y')" placeholder="未选中" style="width: 100%" />
            </a-form-model-item>
          </a-collapse-panel>
          <!-- 数值型的样式 -->
          <a-collapse-panel key="2" header="数值样式">
            <a-form-model-item v-for="item in cellNumStyle" :key="item.val" :label="item.name">
              <a-input v-model="stateForm[item.val]" @blur="ChangeStyleNum(item.val)" @pressEnter="ChangeStyleNum(item.val)" placeholder="" />
            </a-form-model-item>
          </a-collapse-panel>
          <a-collapse-panel key="3" header="颜色样式">
            <!-- 颜色型的样式 -->
            <a-form-model-item v-for="item in cellColorStyle" :key="item.val" :label="item.name">
              <a-input v-model="stateForm[item.val]" type="color" @blur="changeStyleColor(item.val)" placeholder="" />
            </a-form-model-item>
          </a-collapse-panel>
          <a-collapse-panel key="4" header="文字样式">
            <a-button :type="tmpFontStyleArr.length && tmpFontStyleArr.includes('1') ? 'primary' : ''" shape="circle" @click="fontStyle(1)">B</a-button>
            <a-button :type="tmpFontStyleArr.length && tmpFontStyleArr.includes('2') ? 'primary' : ''" shape="circle" @click="fontStyle(2)" style="margin-left: 15px;"><i>I</i></a-button>
            <a-button :type="tmpFontStyleArr.length && tmpFontStyleArr.includes('4') ? 'primary' : ''" shape="circle" @click="fontStyle(4)" style="margin-left: 15px;"><u>U</u></a-button>
            <a-button :type="tmpFontStyleArr.length && tmpFontStyleArr.includes('8') ? 'primary' : ''" shape="circle" @click="fontStyle(8)" style="margin-left: 15px;"><s>S</s></a-button>
          </a-collapse-panel>
        </a-collapse>
        <a-form-model-item label="文字内容">
          <a-input v-model="stateForm.value" @blur="ChangeVal" @pressEnter="ChangeVal" placeholder="" />
        </a-form-model-item>
      </a-form-model>
    </div>
    <!-- 缩略图 -->
    <div class="outline_container" ref="outline_container"></div>
  </div>
</template>

<script>
import mxgraph from '@utils/init.js';
import keyDown from '@utils/initKeyHandler.js';

/**
 * 目前可在状态栏中进行修改的数据有两种来源:
 * 一种是cell.geometry中的数据，包括：width,height,x,y，这种类型数据的修改使用ChangeData函数完成
 * 第二种是cell.style中的数据，包括：opacity，textOpacity，fillOpacity
 * 其中cell.style中的数据又可以分为数值型和字符串类型两种，对于数值型数据的style修改通过ChangeStyleNum
 */

export default {
  name: 'statusPanel',
  module_index: 800,
  module_name: '状态栏',
  data() {
    return {
      editor: null,
      graph: null,
      parent: null,
      num: 0,
      // 构造一个事件处理程序，该处理程序使用橡皮筋选择来选择图中的矩形区域。
      rubberBand: null,

      // cell.style中的num类型数据
      cellNumStyle: [
        { val: 'opacity',name: '不透明度',default: 100,max: 100,min: 0,},
        { val: 'textOpacity',name: '文字不透明度',default: 100,max: 100,min: 0,},
        { val: 'fillOpacity',name: '填充不透明度',default: 100,max: 100,min: 0,},
        { val: 'strokeOpacity',name: '描边不透明度',default: 100,max: 100,min: 0,},
        { val: 'strokeWidth',name: '边框宽度',default: 1,max: 100,min: 1,},
        { val: 'fontSize',name: '字体大小',default: 11,max: 100,min: 1,},
        { val: 'rotation',name: '旋转',default: 0,max: 0,min: 360,},
      ],
      // cell.style中的color类型数据
      cellColorStyle: [
        { val: 'strokeColor',name: '边框颜色',default: '#6482b9' },
        { val: 'fontColor',name: '字体颜色',default: '#774400' },
        { val: 'fillColor',name: '填充颜色',default: '#c3d9ff' },
      ],

      /**
       *   fontArr这个属性的暂存区，这是一个我自己使用并不会被mxgraph解析的属性
       *   mxgraph的字体属性(粗体、斜体、下划线、删除线)是以加和的形式存放在cell.style
       *  中的，仅仅是一个加和之后的数值，对于显示当前已经添加了哪些属性很不友好，因此
       * 自定义此属性，且同样寄存在cell.style中，用于显示当前已添加哪些属性（就是哪些按钮需要高亮显示）
      */
      tmpFontStyleArr: [],

      // 存放展示在状态栏中的数据
      stateForm: {},
    };
  },
  computed: {
    getSelectCell() {
      return this.graph && this.graph.getSelectionCells()
    }
  },
  watch: {
    getSelectCell(n,o) {
      if (n.length != '1') {
        this.stateFormReset();
        return;
      };
      let tmpCell = this.graph.getSelectionCells()[0];
      // 展示信息到form中
      let tmpData = tmpCell.geometry;
      this.stateForm.width = Number(tmpData.width);
      this.stateForm.height = Number(tmpData.height);
      this.stateForm.x = Number(tmpData.x);
      this.stateForm.y = Number(tmpData.y);
      this.stateForm.value = tmpCell.value;

      this.stateForm.opacity = 100;
      this.stateForm.textOpacity = 100;
      this.stateForm.fillOpacity = 100;


      this.stateForm.fontArr = '';
      this.stateForm.fontStyle = 0;

      // 赋予指定默认值-数值部分
      this.cellNumStyle.forEach(item => {
        this.stateForm[item.val] = item.default;
      })
      // 赋予指定默认值-颜色部分
      this.cellColorStyle.forEach(item => {
        this.stateForm[item.val] = item.default;
      })
      // 获取cell的样式信息
      let tmpStyle = tmpCell.style && tmpCell.style.split(';');
      if (tmpStyle) {
        // 如果有非默认属性的style
        [...this.cellNumStyle,...this.cellColorStyle].forEach(item => {
          if (tmpStyle.find(item2 => item2.indexOf([item.val]) != -1)) {
            let index = tmpStyle.findIndex(item2 => item2.indexOf([item.val]) != -1);
            let i = tmpStyle[index].indexOf('=');
            this.stateForm[item.val] = tmpStyle[index].substring(i + 1);
          }
        })
      }
      this.tmpFontStyleArr = [];
      // 字体样式信息展示
      if (tmpStyle && tmpStyle.find(item => item.indexOf('fontArr') != -1)) {
        this.tmpFontStyleArr = JSON.parse(JSON.stringify(tmpStyle.find(item => item.indexOf('fontArr') != -1).substring(8).split(',')));
      }
      console.log(tmpStyle)
      console.log(this.tmpFontStyleArr)
    }
  },
  created() { },
  mounted() {
    this.init();
    this.initRightEvens();
  },
  methods: {
    init() {
      this.editor = new mxEditor()
      // 创建全局容器
      //   this.graph = new mxGraph(this.$refs.graphContainer);
      this.graph = this.editor.graph;
      this.editor.setGraphContainer(this.$refs.graphContainer);
      // 创建全局父元素
      this.parent = this.graph.getDefaultParent();

      //   mxEvent.disableContextMenu(this.$refs.graphContainer);
      this.rubberBand = new mxRubberband(this.graph)
      keyDown(this.graph);

      // 创建缩略图
      this.outline = new mxOutline(this.graph,this.$refs.outline_container);
      // 鼠标滑过高亮
      new mxCellTracker(this.graph,'#ff0');
    },
    stateFormReset() {
      for (let item in this.stateForm) {
        this.stateForm[item] = 0;
      }
    },
    // 数值文本框中的减号触发
    btnJian(valType,funType) {
      // valType表示被修改的是stateForm中的那个数据
      // funType表示这个数据的来源是cell.geometry还是cell.style或者别的
      this.stateForm[valType] -= 10;
      switch (funType) {
        case 1:   // 修改cell.geometry中的数值类型数据
          this.ChangeData(valType)
          break;
        case 2:   // 修改cell.style中的数值类型数据
          this.ChangeStyleNum(valType)
      }
    },
    createGraph() {
      ++this.num;
      var v1 = this.graph.insertVertex(this.parent,'Hello','Hello',Number(((this.num) + Math.random() * 1080).toFixed(2)),Number(((this.num) + Math.random() * 570).toFixed(2)),80,30,'shape=Arrow Down');
      ++this.num;
      var v2 = this.graph.insertVertex(this.parent,'World','World',Number(((this.num) + Math.random() * 1080).toFixed(2)),Number(((this.num) + Math.random() * 570).toFixed(2)),80,30,'strokeColor=#ff0000');
      ++this.num;
      var v3 = this.graph.insertVertex(this.parent,'everyBody!','everyBody!',Number(((this.num) + Math.random() * 1080).toFixed(2)),Number(((this.num) + Math.random() * 570).toFixed(2)),60,60,'opacity=50');
      this.graph.insertEdge(v1,'v1-v2','',v1,v2);
      this.graph.insertEdge(v2,'v2-v3','',v2,v3,'edgeStyle=orthogonalEdgeStyle;');
      this.graph.insertEdge(v3,'v3-v1','',v3,v1);
    },
    initRightEvens() {
      // 这里无需再添加右键菜单的样式，因为之前页面中关于右键菜单的样式没有添加scoped隔离，所以这里的右键菜单依然可以享受之前设置的样式而无需单独设置
      this.graph.popupMenuHandler.factoryMethod = (menu,cell) => {
        menu.addItem(cell ? '查看当前元素状态' : '未选中任何内容',null,() => {
          // getSelectionCells: 返回所选mxCells的数组。
          //   cell.geometry.x += 50;
          //   this.graph.refresh();
        },undefined,undefined,!!cell)
        // addSeparator：在给定父项目中添加水平分隔符，如果未指定父项目，则在顶级菜单中添加水平分隔符。
        menu.addSeparator()
      }
    },
    // 改变cell.geometry的属性内容
    ChangeData(name,name2 = false) {
      if (this.graph.getSelectionCells().length != 1) return;
      this.graph.getSelectionCells()[0].geometry[name] = this.stateForm[name2 || name];
      this.graph.refresh();
    },
    // 改变cell.value
    ChangeVal() {
      if (this.graph.getSelectionCells().length != 1) return;
      this.graph.getSelectionCells()[0].value = this.stateForm.value;
      this.graph.refresh();
    },
    // 改变STYLE中的NUM类型属性
    ChangeStyleNum(type) {
      if (this.graph.getSelectionCells().length != 1) return;
      // TODO: num值合法性待验证，过大或者过小
      this.ChangeCellStyleItem(type,this.stateForm[type])
      this.graph.refresh();
    },
    // 改变STYLE中的color类型属性
    changeStyleColor(type) {
      if (this.graph.getSelectionCells().length != 1) return;
      this.ChangeCellStyleItem(type,this.stateForm[type])
      this.graph.refresh();
    },
    // 修改字体样式
    fontStyle(num) {
      if (this.graph.getSelectionCells().length != 1) return;
      let tmpCell = this.graph.getSelectionCells()[0];
      let arr = [];     // 当前cell所拥有的字体相关样式，而不是加和之后的数值
      if (tmpCell.style && tmpCell.style.indexOf('fontArr') != -1) {
        let tmp = tmpCell.style.split(';').find(item => item.indexOf('fontArr') != -1);
        arr = tmp.substring(8).split(',')
        if (arr.indexOf(num + '') != -1) {
          arr.splice(arr.indexOf(num + ''),1);
        } else {
          arr.push(num + '');
        }
      } else {
        // 如果这个cell之前从没有过这样的样式
        arr.push(num + '')
      }
      let sum = 0;
      arr.forEach(item => sum += Number(item))
      this.tmpFontStyleArr = JSON.parse(JSON.stringify(arr));


      this.ChangeCellStyleItem('fontArr',arr.join(','));
      this.ChangeCellStyleItem('fontStyle',sum);

      this.graph.refresh();
    },
    // 改变cell.style中的某个值
    ChangeCellStyleItem(type,value) {
      let tmpCell = this.graph.getSelectionCells()[0];
      if (tmpCell.style && tmpCell.style.indexOf(type) != -1) {
        // 已有当前要改变样式相关样式
        let styleArr = tmpCell.style.split(';')
        let index = styleArr.findIndex(item => item.indexOf(type) != -1);  // 相关样式在样式数组中的位置
        styleArr[index] = styleArr[index].substring(0,type.length + 1) + value;   // 删除原有数值并拼接新数值
        this.graph.getModel().setStyle(tmpCell,styleArr.join(';'))
      } else {
        // 无样式或者无type相关样式
        this.graph.getModel().setStyle(tmpCell,tmpCell.style += ';' + type + '=' + value);
      }
    },
    // 放大
    zoomIn() {
      this.graph.zoomIn()
    },
    // 缩小
    zoomOut() {
      this.graph.zoomOut()
    },
    // 恢复
    actualSize() {
      this.editor.execute('actualSize');
    },
    // 展示
    show() {
      this.editor.execute('show');
    },
  },

};
</script>
<style>
.ant-row.ant-form-item {
  margin-bottom: 0;
}
</style>
<style scoped>
.status-info-panel {
  position: fixed;
  top: 20%;
  right: 5%;
  padding: 20px;
  background: #fff;
}
.outline_container {
  position: fixed;
  top: 3%;
  right: 7%;
  width: 135px;
  height: 75px;
  border: 1px solid #ccc;
}
span.num-input-slot-btn {
  color: red;
  display: inline-block;
  height: 100%;
  width: 20px;
  background: blue;
}
</style>